package puntaelena.facilitylocation.hillclimbing.experiment.grszcompetitive;

import puntaelena.facilitylocation.hillclimbing.solver.PEHillClimbingAlgorithmBuilder;
import puntaelena.graphsupport.GraphSupportFront;
import puntaelena.graphsupport.solver.IFacilityLocationSolver;
import puntaelena.graphsupport.IGraphGenerator;
import laboratoryQ.experiment.settings.BaseExperimentSettings;
import laboratoryQ.experiment.settings.SettingsAnnotations.*;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.LinkedHashMap;

public class PElenaGSCExperimentSettings extends BaseExperimentSettings {
	@IgnoreWhenCheck
	@Hidden
	public static final IFacilityLocationSolver FACTOR3_SOLVER =
		GraphSupportFront.getFactor3Solver();
	@IgnoreWhenCheck
	@Hidden
	public static final IFacilityLocationSolver[] SOLVERS =
		new IFacilityLocationSolver[] {
			GraphSupportFront.getTrivialSolver(),
			FACTOR3_SOLVER,
			null,
//			new HillClimbingSolver(FACTOR3_SOLVER, false),
			null,
//			new HillClimbingSolver(FACTOR3_SOLVER, true),
			null,
		};
	@IgnoreWhenCheck
	@Hidden
	private static final Map<Integer, Integer> BENEFIT_ENTRS; // TODO: move field 2 extractor
	static {
		PEHillClimbingAlgorithmBuilder builder =
			new PEHillClimbingAlgorithmBuilder();
		builder.addForAllCitiesRelinkTheBest();
		builder.addForChpUsflClsdFcltOpenRelikn();
		SOLVERS[2] = builder.build();
		builder.addForFacilitySearchesAndClosesEnemies();
		SOLVERS[3] = builder.build();
		builder = new PEHillClimbingAlgorithmBuilder();
		builder.addForAllCitiesRelinkTheBest();
//		builder.addForChpUsflClsdFcltOpenRelikn();
		builder.addWhileClosedFacilitiesCoalitions();
		SOLVERS[4] = builder.build();

		Map<Integer, Integer> bmap = new LinkedHashMap<Integer, Integer>();
		bmap.put(3, 2);
		bmap.put(4, 2);
		BENEFIT_ENTRS = bmap;
	}

	@IgnoreWhenCheck
	@Hidden
	public IFacilityLocationSolver[] solvers = SOLVERS;
	@IgnoreWhenCheck
	@Hidden
	private Map<Integer, Integer> benefitObservationItems = BENEFIT_ENTRS;

	@IgnoreWhenCheck
	@Hidden
	private IGraphGenerator graphGenerator = GraphSupportFront.expensiveCheapGenerator();

	@Increase(value = 50, boundBegin = 50, boundEnd = 1000)
	public int citiesCountBeg = -1;
	@Increase(value = 50, boundBegin = 100, boundEnd = 1000)
	public int citiesCountEnd = -1;

	@Increase(value = 20, boundBegin = 5, boundEnd = 300)
	public int facilitiesCountBeg = -1;
	@Increase(value = 20, boundBegin = 5, boundEnd = 300)
	public int facilitiesCountEnd = -1;

	@Increase(value = 1, boundBegin = 1, boundEnd = 100)
	public int eachExperimentRunsCount = -1;
	
	@Increase(value = 1, boundBegin = 2, boundEnd = 150)
	public int neighborCountBeg = -1;
	@Increase(value = 1, boundBegin = 1, boundEnd = 100)
	public int neighborCountRange = -1;

	@Increase(value = 20, boundBegin = 0, boundEnd = Double.MAX_VALUE)
	public double cheapEdgeBeg = -1;
	@Increase(value = 10, boundBegin = 1, boundEnd = Double.MAX_VALUE) // TODO: range -- double in cpp !
	public double cheapEdgeRange = -1;
	@Increase(value = 20, boundBegin = 0, boundEnd = Double.MAX_VALUE)
	public double expensiveEdgeBeg = -1;
	@Increase(value = 10, boundBegin = 1, boundEnd = Double.MAX_VALUE)
	public double expensiveEdgeRange = -1;

	@Increase(value = 20, boundBegin = 0, boundEnd = Double.MAX_VALUE)
	public double facilityPriceBeg = -1;
	@Increase(value = 10, boundBegin = 1, boundEnd = Double.MAX_VALUE)
	public double facilityPriceRange = -1;

	@Increase(value = 1, boundBegin = 0, boundEnd = 1)
	public boolean triangleIneqEnabled = false;

	public PElenaGSCExperimentSettings() {
		experimentContextFactory = new PElenaGSCContextFactory();
		experiment = new PElenaGSCExperiment();
	}

	public IGraphGenerator getGraphGenerator() {
		return graphGenerator;
	}

	public Set<Entry<Integer,Integer>> getBenefitObservationItems() {
		return benefitObservationItems.entrySet();
	}
}
